package novel.front.novellist.controller.wx;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import novel.common.constant.IConstInfo;
import novel.common.utils.string.StringUntils;
import novel.common.utils.weixin.SignUtil;
import novel.common.utils.weixin.WxCoreService;
import novel.common.utils.weixin.message.HttpUtil;
import novel.common.web.BaseController;
import novel.front.novellist.entity.ExitOrder;
import novel.front.novellist.entity.WxOrder;
import novel.front.novellist.service.ExitOrderService;
import novel.front.novellist.service.WxOrderService;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.*;

/**
 * Created by sutong on 2017/11/1.
 */
@Controller
@RequestMapping("wx2")
public class wxController extends BaseController {
  public static final String url = "https://www.oloffe.com";
  @Resource
  private WxOrderService wxOrderService;

  @Resource
  private ExitOrderService exitOrderServic;

  @RequestMapping("/test")
  public String test() {
    return "wx/success";
  }

  @RequestMapping("/test2")
  public String test2() {
    return "wx/cliTest";
  }

  @RequestMapping(value = "/interface", method = RequestMethod.GET)
  public void get(HttpServletRequest request, HttpServletResponse response) {
    // 微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
    String signature = request.getParameter("signature");
    // 时间戳
    String timestamp = request.getParameter("timestamp");
    // 随机数
    String nonce = request.getParameter("nonce");
    // 随机字符串
    String echostr = request.getParameter("echostr");

    PrintWriter out = null;
    try {
      out = response.getWriter();
      // 通过检验signature对请求进行校验，若校验成功则原样返回echostr，否则接入失败
      if (SignUtil.checkSignature(signature, timestamp, nonce)) {
        out.print(echostr);
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      out.close();
      out = null;
    }
  }

  @RequestMapping(value = "/interface", method = RequestMethod.POST)
  public void post(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("调用到了");

    // 消息的接收、处理、响应
    // 将请求、响应的编码均设置为UTF-8（防止中文乱码）
    try {
      request.setCharacterEncoding("UTF-8");
      response.setCharacterEncoding("UTF-8");

      // 调用核心业务类接收消息、处理消息
      String respXml = WxCoreService.processRequest(request);
      System.out.println("返回的xml:" + respXml);
      // 响应消息
      PrintWriter out = response.getWriter();
      out.print(respXml);
      out.flush();
      out.close();
    } catch (UnsupportedEncodingException e) {
      System.out.println(e);
      e.printStackTrace();
    } catch (IOException e) {
      System.out.println(e);
      e.printStackTrace();
    }
  }


  /***
   * 微信订单支付页面
   *
   * @param request
   * @param response
   * @return
   * @throws IOException
   */
  @RequestMapping(value = "/toPay", method = RequestMethod.GET)
  public String toPay(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
    return "";
  }

  /**
   * 微信订单支付
   *
   * @param request
   * @param model
   * @return
   * @throws Exception
   */
  @RequestMapping(value = "/wxPay", method = RequestMethod.POST)
  @ResponseBody
  public String wxPay(HttpServletRequest request, Model model) throws Exception {
    return "";
  }


  /**
   * 订单支付调函数被调用页面
   *
   * @return
   */
  @RequestMapping("/wXcallBack")
  @ResponseBody
  public void wXcallBack(HttpServletRequest request, HttpServletResponse response) {

  }

  /**
   * 生成二维码输入界面
   *
   * @param request
   * @param model
   * @return
   * @throws Exception
   */
  @RequestMapping(value = "/wxxewcwes", method = RequestMethod.GET)
  public String wx(HttpServletRequest request, Model model) throws Exception {
    String code = request.getParameter("code");
    if (StringUntils.isEmpty(code)) {
      return "wx/err";
    }
    String openid = getOpenId(code);
    if (StringUntils.isEmpty(openid)) {
      return "wx/err";
    }
    System.out.println("需要验证的openid");
    String openid1 = "oIIq-w8EoHgIFch5WGtmP4XjJnQQ";
    String openid2 = "oIIq-w8PUWIAkqzeN_PBxaD6nHT8";
    String uuid = UUID.randomUUID().toString().toUpperCase().replaceAll("-", "").replaceAll("_", "");
    ExitOrder exitOrder = new ExitOrder();
    exitOrder.setWxUuid(uuid);
    exitOrderServic.insert(exitOrder);
    model.addAttribute("uuid", uuid);
    //https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx2a53c0d30ca36420&redirect_uri=http://www.kukuwu.com/wx/wx?response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
    if (openid1.equals(openid) || openid2.equals(openid)) {
      return "wx/wx";
    }
//        return "wx/wx";
    return "wx/err";
  }

  /**
   * 生成二维码输入界面
   *
   * @param request
   * @param model
   * @return
   * @throws Exception
   */
  @RequestMapping(value = "/qrsrwe", method = RequestMethod.GET)
  public String qrsr(HttpServletRequest request, Model model) throws Exception {
    String amount = request.getParameter("amount");
    String orderCode = request.getParameter("orderCode");
    String uuid = request.getParameter("uuid");
//        String uuid = UUID.randomUUID().toString().toUpperCase().replaceAll("-", "").replaceAll("_", "");
    if (StringUntils.isEmpty(amount) || StringUntils.isEmpty(uuid)) {
      return "wx/err";
    }

    WxOrder exitWxOrder = wxOrderService.selectByPrimaryUuid(uuid);
    if (exitWxOrder != null) {
      return "wx/err";
    }

    ExitOrder exitOrder = exitOrderServic.selectByPrimaryUuid(uuid);
    if (exitOrder == null) {
      return "wx/err";
    }

    WxOrder wxOrder = new WxOrder();
    wxOrder.setAmount(Integer.valueOf(amount));
    wxOrder.setWxUuid(uuid);
    wxOrderService.insert(wxOrder);

    WxOrder wxOrder1 = wxOrderService.selectByPrimaryUuid(uuid);
    if (wxOrder1.getAmount().equals(new Integer(3000))) {
      System.out.println(true);
    }

    model.addAttribute("amount", amount);
    model.addAttribute("orderCode", uuid + "_" + orderCode);
    model.addAttribute("orderId", orderCode);
    return "wx/qrsr";
  }


  /**
   * 订单支付调函数被调用页面
   *
   * @return
   */
  @RequestMapping("/getCode")
  public void getCode(String url, String scope) throws Exception {
    http:
//www.kukuwu.com/wx/getCode?url=www.baidu.com
    if (scope == null) {
      scope = "snsapi_base";
    } else {
      scope = "snsapi_userinfo";
    }
    String code = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + IConstInfo.APP_ID + "&redirect_uri=" + URLEncoder.encode(url, "UTF-8") + "&response_type=code&scope=snsapi_userinfo#wechat_redirect";
    System.out.println("code职位：" + code);
  }

  /*
   * 获取用户微信授权第一步获取code参数 参数 snsapi_base此参数为静默授权，用户看不到授权页面
   * snsapi_userinfo此参数需要用户同意，可获取其用户信息
   *
   * 方法参数 url为回调地址 scope 为授权类型
   */
  public static String getRequestCodeUrl(String url, String scope) throws Exception {
    // scope 为获取授权类型，null为默认授权
    if (scope == null) {
      scope = "snsapi_base";
    } else {
      scope = "snsapi_userinfo";
    }
    String code = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + IConstInfo.APP_ID + "&redirect_uri=" + URLEncoder.encode(url, "UTF-8") + "&response_type=code&scope=" + scope + "#wechat_redirect";
    return code;
  }

  /*
   * 获取用户微信授权第二步获取access_token 根据第一步获取到的code去换取access_token
   * 根据实现步骤不同，此方法只获取到用户openId即为结束 注意，此access_token与基础参数access_token不一样
   *
   * 如若，今后开发需要用户信息等，根据微信API去实现剩余步骤
   */
  public static Map<String, String> getAccessToken(String code) throws Exception {
    long start = System.currentTimeMillis();
    String url = " https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + IConstInfo.APP_ID + "&secret=" + IConstInfo.APP_SECRET + "&code=" + code + "&grant_type=authorization_code";
    String result = null;
    try {
      result = HttpUtil.sendGet(url, "utf-8", 1000);
      System.out.println("-------------------：调用获取网页授权accessToken接口json串" + JSON.parseObject(result));
    } catch (Exception e) {
      e.printStackTrace();
      throw new Exception("发起网络请求出错");
    }
    if (!result.equals("")) {
      JSONObject json = JSON.parseObject(result);
      if (json.get("access_token") != null) {
        Map<String, String> authData = new HashMap<String, String>();
        authData.put("access_token", json.getString("access_token"));
        authData.put("expires_in", json.getString("expires_in"));
        authData.put("refresh_token", json.getString("refresh_token"));
        authData.put("openid", json.getString("openid"));
        authData.put("scope", json.getString("scope"));
        System.out.println("调用获取网页授权accessToken接口耗时-->" + (System.currentTimeMillis() - start) + "毫秒");
        System.out.println("-------------------我是获取openId方法：" + json.getString("openid"));
        return authData;
      } else {
        System.out.println("调用获取网页授权accessToken接口失败-->" + result);
        throw new Exception(result);
      }
    } else {
      throw new Exception("调用获取网页授权accessToken接口返回数据为空");
    }

  }

  /**
   * 获取openId
   *
   * @return
   */
  public static String getOpenId(String code) {
    String openid = "";
    if (StringUntils.isEmpty(code)) {
      System.out.println("code值为空");
    }
    try {
      Map<String, String> authData = getAccessToken(code);
      openid = authData.get("openid");
      System.out.println("-------------------我是获取openId方法：" + authData.get("openid"));
    } catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println("执行到了1");
    return openid;
  }

  /**
   * 扫码转账
   *
   * @return
   */
  @RequestMapping("/scanQr")
  public String scanQr(HttpServletRequest request) {
    String code = request.getParameter("code");
    String openid = getOpenId(code);
    System.out.println("执行到了2：" + openid);
    String amountStr = request.getParameter("amount");
    String oderCodeuuid = request.getParameter("state");
    String uuid = "";
    String oderCode = "";
    if (StringUntils.isEmpty(openid)) {
      System.out.println("openid为空");
      return "wx/err";
    }
    if (StringUntils.isEmpty(amountStr) || !StringUntils.isNumberStr(amountStr)) {
      System.out.println("amount为空");
      return "wx/err";
    }
    System.out.println("执行到了3：" + openid);
    int amount = StringUntils.parseInteger(amountStr) * 100;
    System.out.println("openid为：" + openid);
    System.out.println("amount为：" + amountStr);
    System.out.println("oderCodeuuid：" + oderCodeuuid);

    if (StringUntils.isEmpty(oderCodeuuid) && oderCodeuuid.length() <= 5) {
      System.out.println("oderCodeuuid为空");
      return "wx/err";
    }
    String[] codeArr = oderCodeuuid.split("_");
    if (codeArr.length >= 1) {
      uuid = codeArr[0];
    }
    if (StringUntils.isEmpty(uuid)) {
      System.out.println("uuid");
      return "wx/err";
    }
    if (codeArr.length >= 2) {
      oderCode = codeArr[1];
    }

    //https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx2a53c0d30ca36420&redirect_uri=http://www.kukuwu.com/wx/scanQr?amount=1&response_type=code&scope=snsapi_userinfo&state=1qwe#wechat_redirect
//        amount=100;
    changeMoney(openid, amount, oderCode, uuid);
    return "wx/success";
  }

  private void changeMoney(String openid, int amount, String orderCode, String uuid) {
//        String uuid = UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");
    if (StringUntils.isEmpty(openid)) {
      System.out.println("openid为空");
      return;
    }
    String desc = "酷友卡海外点卡商城";
    if (StringUntils.isNotEmpty(orderCode)) {
      desc += ",订单号：" + orderCode;
    }
//        String partner_trade_no = "1234567890003"; //同一单号不可以重复提交，如果重复提交同一单号，微信以为是同一次付款，只要成功一次，以后都会无视。
    String partner_trade_no = uuid;
    if (amount >= 1000*100) {
      amount = 1000*100;
    }
    WxOrder wxOrder1 = wxOrderService.selectByPrimaryUuid(uuid);
    System.out.println("数据库的金额："+wxOrder1.getAmount());
    System.out.println("输入的金额："+new Integer(amount / 100));
    if (wxOrder1.getAmount().equals(new Integer(amount / 100))) {
      Map<String, String> map = transfer(openid, amount, desc, partner_trade_no);
      if (StringUtils.equals(map.get("state"), "SUCCESS")) {
        System.out.println(map.get("payment_no"));
        System.out.println(map.get("payment_time"));
      } else {
        System.out.println(map.get("err_code"));
        System.out.println(map.get("err_code_des"));
      }
    } else {
      System.out.println("金额错误！");
    }

  }

  public static void main(String[] args) throws Exception {
    System.out.println((new Integer(300)) / 100);
    if (true) {
      //运行main方法，可以测试配置是否正确。配置信息写在同级目录的 weinxin.config.xml里
      String openid = "oIIq-w8EoHgIFch5WGtmP4XjJnQQ";//这是个人的微信openID,欢迎大家给我付款。哈哈。。。。。
//        String openid = "ozn14vx_hi0DkwaO8vcHwJ05Qpv0";//这是个人的微信openID,欢迎大家给我付款。哈哈。。。。。
      int amount = 100;  //最低付款金额为100分。付款金额以分为单位
      String desc = "酷友卡海外点卡商城";
      String partner_trade_no = "12345678910012"; //同一单号不可以重复提交，如果重复提交同一单号，微信以为是同一次付款，只要成功一次，以后都会无视。
      Map<String, String> map = transfer(openid, amount, desc, partner_trade_no);
      if (StringUtils.equals(map.get("state"), "SUCCESS")) {
        System.out.println(map.get("payment_no"));
        System.out.println(map.get("payment_time"));
      } else {
        System.out.println(map.get("err_code"));
        System.out.println(map.get("err_code_des"));
      }
    }
  }


  /**
   * @param openid           收款人的openID(微信的openID)
   * @param amount           付款金额
   * @param desc             付款描述
   * @param partner_trade_no 订单号(系统业务逻辑用到的订单号)
   * @return map{state:SUCCESS/FAIL}{payment_no:
   * '支付成功后，微信返回的订单号'}{payment_time:'支付成功的时间'}{err_code:'支付失败后，返回的错误代码'}{err_code_des:'支付失败后，返回的错误描
   * 述 ' }
   * @throws IOException
   * @throws NoSuchAlgorithmException
   * @throws CertificateException
   * @throws KeyStoreException
   * @throws KeyManagementException
   * @throws UnrecoverableKeyException
   * @throws DocumentException
   * @author 苏国同
   * @date 2016-7-12下午2:29:34
   * @Description：微信支付，企业向个人付款
   */
  private static Map<String, String> transfer(String openid, int amount, String desc, String partner_trade_no) {
    Map<String, String> map = new HashMap<String, String>(); // 定义一个返回MAP
    try {
      // 读取配置文件信息，包括微信支付的APPID，商户ID和证书路径
//            InputStream configFile = wxController.class.getResourceAsStream("weixin.config.xml");
//            SAXReader reader = new SAXReader();
//            Document doc = reader.read(configFile);
//            Element config = doc.getRootElement();
      String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
      InetAddress ia = InetAddress.getLocalHost();
      String ip = ia.getHostAddress(); // 获取本机IP地址
      String uuid = UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");// 随机获取UUID
//            String appid = config.elementTextTrim("appKey");// 微信分配的公众账号ID（企业号corpid即为此appId）
      String appid = IConstInfo.APP_ID;// 微信分配的公众账号ID（企业号corpid即为此appId）
//            String mchid = config.elementTextTrim("mchid");// 微信支付分配的商户号
      String mchid = "1493024302";// 微信支付分配的商户号
      // 设置支付参数
      SortedMap<Object, Object> signParams = new TreeMap<Object, Object>();

      signParams.put("mch_appid", appid); // 微信分配的公众账号ID（企业号corpid即为此appId）
      signParams.put("mchid", mchid);// 微信支付分配的商户号
      signParams.put("nonce_str", uuid); // 随机字符串，不长于32位
      signParams.put("partner_trade_no", partner_trade_no); // 商户订单号，需保持唯一性
      signParams.put("openid", openid); // 商户appid下，某用户的openid
      signParams.put("check_name", "NO_CHECK"); // NO_CHECK：不校验真实姓名
      // FORCE_CHECK：强校验真实姓名（未实名认证的用户会校验失败，无法转账）
      // OPTION_CHECK：针对已实名认证的用户才校验真实姓名（未实名认证用户不校验，可以转账成功）
      signParams.put("amount", amount); // 企业付款金额，单位为分
      signParams.put("desc", desc); // 企业付款操作说明信息。必填。
      signParams.put("spbill_create_ip", ip); // 调用接口的机器Ip地址

      // 生成支付签名，要采用URLENCODER的原始值进行MD5算法！

      String sign = "";
      sign = createSign("UTF-8", signParams);
      // System.out.println(sign);
      String data = "<xml><mch_appid>";
      data += appid + "</mch_appid><mchid>"; // APPID
      data += mchid + "</mchid><nonce_str>"; // 商户ID
      data += uuid + "</nonce_str><partner_trade_no>"; // 随机字符串
      data += partner_trade_no + "</partner_trade_no><openid>"; // 订单号
      data += openid + "</openid><check_name>NO_CHECK</check_name><amount>"; // 是否强制实名验证
      data += amount + "</amount><desc>"; // 企业付款金额，单位为分
      data += desc + "</desc><spbill_create_ip>"; // 企业付款操作说明信息。必填。
      data += ip + "</spbill_create_ip><sign>";// 调用接口的机器Ip地址
      data += sign + "</sign></xml>";// 签名
      System.out.println(data);
      // 获取证书，发送POST请求；
      KeyStore keyStore = KeyStore.getInstance("PKCS12");
//            FileInputStream instream = new FileInputStream(new File("C:\\cert\\apiclient_cert.p12")); // 从配置文件里读取证书的路径信息
      FileInputStream instream = new FileInputStream(new File("//home//cert2//apiclient_cert.p12")); // 从配置文件里读取证书的路径信息
      keyStore.load(instream, mchid.toCharArray());// 证书密码是商户ID
      instream.close();
      SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchid.toCharArray()).build();
      SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
      CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
      HttpPost httpost = new HttpPost(url); //
      httpost.addHeader("Connection", "keep-alive");
      httpost.addHeader("Accept", "*/*");
      httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
      httpost.addHeader("Host", "api.mch.weixin.qq.com");
      httpost.addHeader("X-Requested-With", "XMLHttpRequest");
      httpost.addHeader("Cache-Control", "max-age=0");
      httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
      httpost.setEntity(new StringEntity(data, "UTF-8"));
      CloseableHttpResponse response = httpclient.execute(httpost);
      HttpEntity entity = response.getEntity();

      String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
      EntityUtils.consume(entity);
      // 把返回的字符串解释成DOM节点
      Document dom = DocumentHelper.parseText(jsonStr);
      Element root = dom.getRootElement();
      String returnCode = root.element("result_code").getText(); // 获取返回代码
      if (StringUtils.equals(returnCode, "SUCCESS")) { // 判断返回码为成功还是失败
        String payment_no = root.element("payment_no").getText(); // 获取支付流水号
        String payment_time = root.element("payment_time").getText(); // 获取支付时间
        map.put("state", returnCode);
        map.put("payment_no", payment_no);
        map.put("payment_time", payment_time);
        return map;
      } else {
        String err_code = root.element("err_code").getText(); // 获取错误代码
        String err_code_des = root.element("err_code_des").getText();// 获取错误描述
        map.put("state", returnCode);// state
        map.put("err_code", err_code);// err_code
        map.put("err_code_des", err_code_des);// err_code_des
        return map;
      }

    } catch (DocumentException ex) {
      ex.printStackTrace();
      return map;
    } catch (UnrecoverableKeyException ex) {
      ex.printStackTrace();
      return map;
    } catch (KeyManagementException ex) {
      ex.printStackTrace();
      return map;
    } catch (KeyStoreException ex) {
      ex.printStackTrace();
      return map;
    } catch (CertificateException ex) {
      ex.printStackTrace();
      return map;
    } catch (IOException ex) {
      ex.printStackTrace();
      return map;
    } catch (NoSuchAlgorithmException ex) {
      ex.printStackTrace();
      return map;
    }
  }

  /**
   * @param characterEncoding 编码格式
   * @param parameters        请求参数
   * @return
   * @author 苏国同
   * @date 2016-7-5下午2:29:34
   * @Description：sign签名
   */
  private static String createSign(String characterEncoding, SortedMap<Object, Object> parameters) {
    StringBuffer sb = new StringBuffer();
    Set<Map.Entry<Object, Object>> es = parameters.entrySet();
    Iterator<Map.Entry<Object, Object>> it = es.iterator();
    while (it.hasNext()) {
      Map.Entry<Object, Object> entry = it.next();
      String k = (String) entry.getKey();
      Object v = entry.getValue();
      if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
        sb.append(k + "=" + v + "&");
      }
    }
    sb.append("key=" + "zhongguosgtweixinkaifa1234567898");
    String sign = MD5Encode(sb.toString(), characterEncoding).toUpperCase();
    return sign;
  }

  // MD5Util工具类中相关的方法

  private static String byteArrayToHexString(byte b[]) {
    StringBuffer resultSb = new StringBuffer();
    for (int i = 0; i < b.length; i++)
      resultSb.append(byteToHexString(b[i]));

    return resultSb.toString();
  }

  private static String byteToHexString(byte b) {
    int n = b;
    if (n < 0)
      n += 256;
    int d1 = n / 16;
    int d2 = n % 16;
    return hexDigits[d1] + hexDigits[d2];
  }

  private static String MD5Encode(String origin, String charsetname) {
    String resultString = null;
    try {
      resultString = new String(origin);
      MessageDigest md = MessageDigest.getInstance("MD5");
      if (charsetname == null || "".equals(charsetname))
        resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
      else
        resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
    } catch (Exception exception) {
    }
    return resultString;
  }

  private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
}


